package com.wellsoft.pt.app.dingtalk.service.impl;

import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.google.common.collect.Maps;
import com.wellsoft.context.enums.IdPrefix;
import com.wellsoft.context.jdbc.support.QueryItem;
import com.wellsoft.context.util.PinyinUtil;
import com.wellsoft.pt.app.dingtalk.dao.MultiOrgDingDeptDao;
import com.wellsoft.pt.app.dingtalk.dao.MultiOrgDingUserInfoDao;
import com.wellsoft.pt.app.dingtalk.entity.MultiOrgDingUserInfo;
import com.wellsoft.pt.app.dingtalk.service.MultiOrgDingUserInfoService;
import com.wellsoft.pt.app.dingtalk.utils.DingtalkApiUtils;
import com.wellsoft.pt.jpa.service.impl.AbstractJpaServiceImpl;
import com.wellsoft.pt.multi.org.bean.OrgTreeNodeVo;
import com.wellsoft.pt.multi.org.bean.OrgUserVo;
import com.wellsoft.pt.multi.org.entity.MultiOrgTreeNode;
import com.wellsoft.pt.multi.org.facade.service.MultiOrgService;
import com.wellsoft.pt.multi.org.facade.service.MultiOrgUserAccountFacadeService;
import com.wellsoft.pt.security.audit.bean.RoleBean;
import com.wellsoft.pt.security.audit.entity.Role;
import com.wellsoft.pt.security.audit.facade.service.RoleFacadeService;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * Description: 钉钉用戶信息service实现类
 * 
 * @author bryanlin
 * @date 2020年5月18日
 * @version 1.0
 * 
 *          <pre>
 * 修改记录:
 * 修改后版本	修改人		修改日期			修改内容
 * 2020年5月18日.1	bryanlin		2020年5月18日		Create
 *          </pre>
 *
 */
@Service
@PropertySource(value = "classpath:system-pt-dingtalk.properties")
public class MultiOrgDingUserInfoServiceImpl extends
		AbstractJpaServiceImpl<MultiOrgDingUserInfo, MultiOrgDingUserInfoDao, String> implements
		MultiOrgDingUserInfoService {

	private Logger logger = LoggerFactory.getLogger(MultiOrgDingUserInfoServiceImpl.class);

	@Value("${pt.system_unit_id}")
	private String system_unit_id;

	@Value("${pt.org_version_id}")
	private String org_version_id;

	@Autowired
	private MultiOrgService multiOrgService;

	@Autowired
	private MultiOrgUserAccountFacadeService multiOrgUserAccountService;

	@Autowired
	private MultiOrgDingDeptDao multiOrgDingDeptDao;

	@Autowired
	private RoleFacadeService roleFacadeService;

	@Override
	public void saveUserFromDingtalkEventCallBack(JSONArray userIds, String eventType) {
		for (int i = 0; i < userIds.size(); i++) {
			String userId = userIds.get(i).toString();
			String accessToken = DingtalkApiUtils.getAccessToken(); // 重新获取access_token
			this.addUserFromDingtalk(userId, accessToken);
		}
	}

	private String addRolesFromDingtalk(JSONArray roles) {
		String roleUuids = "";
		if (roles.size() == 0)
			return roleUuids;
		for (int i = 0; i < roles.size(); i++) {
			JSONObject role = roles.getJSONObject(i);
			String roleName = role.getString("name");
			String uuid = this.getRoleByName(roleName);
			if (StringUtils.isEmpty(uuid)) {
				RoleBean roleBean = new RoleBean();
				roleBean.setName(roleName);
				roleBean.setCode(currentDateStr() + i);
				roleBean.setId(currentDateStr() + RandomStringUtils.randomNumeric(6));
				roleBean.setSystemUnitId(system_unit_id);
				//this.roleFacadeService.saveBean(roleBean);

				Role roleEntity = new Role();
				BeanUtils.copyProperties(roleBean, roleEntity);
				roleFacadeService.save(roleEntity);
				roleUuids += roleEntity.getUuid() + ";";
			} else {
				roleUuids += uuid + ";";
			}
		}
		return roleUuids.substring(0, roleUuids.length() - 1);
	}

	private String currentDateStr() {
		Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		String monthStr = "" + month;
		int day = c.get(Calendar.DAY_OF_MONTH);
		String dayStr = "" + day;
		if (month < 10) {
			monthStr = "0" + monthStr;
		}
		if (day < 10) {
			dayStr = "0" + dayStr;
		}
		return "" + year + monthStr + dayStr;
	}

	/**
	 * 添加职位
	 * @param departments
	 * @param position
	 * @return
	 */
	private Map<String, Object> addJobFromDingtalkPosition(JSONArray departments, String position) {
		Map<String, Object> map = new HashMap<>();
		if (CollectionUtils.isEmpty(departments)) {
			return null;
		}
		String deptId = departments.get(0).toString(); // 给第一个部门添加职位
		QueryItem item = this.multiOrgDingDeptDao.getNodeInfoByDingtalkDeptId(Integer.parseInt(deptId));
		Map<String, Object> p = new HashMap<>();
		p.put("jobName", position);
		List<QueryItem> list = this.dao.listQueryItemByNameSQLQuery("getJobByName", p, null);// 是否在部门下已存在职位
		if (item != null && list.size() == 0) {
			String pPath = item.getString("path");
			String pname = item.getString("name");
			// 构造部门VO
			OrgTreeNodeVo nodevo = new OrgTreeNodeVo();
			nodevo.setName(position);
			nodevo.setShortName(position);
			nodevo.setCode("0000" + RandomStringUtils.randomNumeric(3));
			nodevo.setType(IdPrefix.JOB.getValue()); // 类型
			nodevo.setParentEleIdPath(pPath);
			nodevo.setParentEleNamePath(pname);
			nodevo.setOrgVersionId(org_version_id);
			nodevo.setSystemUnitId(system_unit_id);
			MultiOrgTreeNode node = multiOrgService.addOrgChildNode(nodevo);
			// if(i == 0) {
			map.clear();
			map.put("mainJobId", org_version_id + "/" + node.getEleId());
			map.put("mainJobNamePath", position);
		} else {
			map.put("mainJobId", org_version_id + "/" + list.get(0).getString("id"));
			map.put("mainJobNamePath", position);
		}
		return map;
	}

	/**
	 * 通过角色名称查找角色信息
	 * @param roleName
	 * @param systemUnitId
	 * @return
	 */
	private String getRoleByName(String roleName) {
		Map<String, Object> params = new HashMap<>();
		params.put("systemUnitId", system_unit_id);
		params.put("roleName", roleName);
		List<QueryItem> list = this.dao.listQueryItemByNameSQLQuery("getRoleByName", params, null);
		if (list.size() > 0) {
			QueryItem item = list.get(0);
			return item.getString("uuid");
		}
		return "";
	}

	@Override
	public QueryItem getMultiOrgDingUserInfoByMap(String unionid, String userId) {
		Map<String, Object> map = new HashMap<>();
		map.put("unionid", unionid);
		map.put("userId", userId);
		List<QueryItem> list = this.dao.listQueryItemByNameSQLQuery("getMultiOrgDingUserInfoByMap", map, null);
		if (list.size() > 0)
			return list.get(0);
		return null;
	}

	@Override
	public void addUserFromDingtalk(String userId, String accessToken) {
		JSONObject userobj = DingtalkApiUtils.getDingTalkUserInfo(userId, accessToken); // 调取钉钉接口获取用户详情
		addUserFromDingtalk(userobj);
	}

	@Override
	@Transactional
	public void addUserFromDingtalk(JSONObject userobj) {
		// TODO Auto-generated method stub
		if (userobj != null) {
			String unionid = userobj.getString("unionid");
			String userId = userobj.getString("userid");

			String orderInDepts = userobj.get("orderInDepts") == null ? "" : userobj.getString("orderInDepts");
			String openId = userobj.get("openId") == null ? "" : userobj.getString("openId");
			String mobile = userobj.get("mobile") == null ? "" : userobj.getString("mobile");
			boolean active = userobj.get("active") == null ? false : userobj.getBoolean("active");
			String avatar = userobj.get("avatar") == null ? "" : userobj.getString("avatar");
			boolean isAdmin = userobj.get("isAdmin") == null ? false : userobj.getBoolean("isAdmin");
			String tags = userobj.get("tags") == null ? "" : userobj.getJSONObject("tags").toString();
			boolean isHide = userobj.get("isHide") == null ? false : userobj.getBoolean("isHide");
			String isLeaderInDepts = userobj.get("isLeaderInDepts") == null ? "" : userobj.getString("isLeaderInDepts");
			boolean isBoss = userobj.get("isBoss") == null ? false : userobj.getBoolean("isBoss");
			boolean isSenior = userobj.get("isSenior") == null ? false : userobj.getBoolean("isSenior");
			String name = userobj.get("name") == null ? "" : userobj.getString("name");
			String stateCode = userobj.get("stateCode") == null ? "" : userobj.getString("stateCode");
			String email = userobj.get("email") == null ? "" : userobj.getString("email");
			// 角色 
			JSONArray roles = userobj.get("roles") == null ? new JSONArray() : userobj.getJSONArray("roles");
			String roleUuids = addRolesFromDingtalk(roles);
			// 部门
			JSONArray departments = userobj.getJSONArray("department");
			// 职位  用户多部门的时候，同时在不同部门新增该职位。
			String position = userobj.getString("position");
			Map<String, Object> map = addJobFromDingtalkPosition(departments, position);

			// 登录名为拼音全拼  TODO 存在中文转拼音后，重名的问题，导致数据无法插入？
			// fixed 名称再加已存在的排序+1，例如已存在两个linyu，linyu2，则后续为拼音重复时，为linyu3
			String loginName = PinyinUtil.getPinYin(name);

			QueryItem item = this.getMultiOrgDingUserInfoByMap(unionid, userId);
			if (item != null) {
				return;
			}
			loginName = getLoginName(loginName);

			OrgUserVo orgUserVo = new OrgUserVo();
			orgUserVo.setLoginName(loginName); // 平台登录名称使用手机号，保证唯一性
			orgUserVo.setCode(userId); // userid为钉钉返回的用户标识，这边作为code写入，后续平台可自行修改
			orgUserVo.setType(0);
			orgUserVo.setIsForbidden(0);
			orgUserVo.setSystemUnitId(system_unit_id);
			orgUserVo.setIsLocked(0);
			orgUserVo.setMobilePhone(mobile);
			orgUserVo.setMainEmail(email);
			orgUserVo.setUserName(name);
			orgUserVo.setRoleUuids(roleUuids);
			if (map != null) {
				orgUserVo.setMainJobId(map.get("mainJobId").toString());
				orgUserVo.setMainJobNamePath(map.get("mainJobNamePath").toString());
				//				orgUserVo.setMainDepartmentIdPath(map.get("mainDepartmentIdPath").toString());
				//				orgUserVo.setMainDepartmentNamePath(map.get("mainDepartmentNamePath").toString());
			}
			orgUserVo = multiOrgService.addUser(orgUserVo);

			MultiOrgDingUserInfo userInfo = new MultiOrgDingUserInfo();
			userInfo.setName(name);
			userInfo.setUnionId(unionid);
			userInfo.setOrderInDepts(orderInDepts);
			userInfo.setOpenId(openId);
			userInfo.setRoles(roles.toString());
			userInfo.setMobile(mobile);
			userInfo.setActive(active ? 1 : 0);
			userInfo.setIsAdmin(isAdmin ? 1 : 0);
			userInfo.setIsHide(isHide ? 1 : 0);
			userInfo.setIsLeaderInDepts(isLeaderInDepts);
			userInfo.setIsBoss(isBoss ? 1 : 0);
			userInfo.setIsSenior(isSenior ? 1 : 0);
			userInfo.setStateCode(stateCode);
			userInfo.setDepartment(departments.toString());
			userInfo.setEmail(email);
			userInfo.setPosition(position);
			userInfo.setUserId(orgUserVo.getId());
			userInfo.setDing_userId(userId);
			userInfo.setAvatar(avatar);
			userInfo.setTags(tags);
			userInfo.setPtOriginPwd("0"); // 默认密码
			this.dao.save(userInfo);
		}
	}

	private String getLoginName(String loginName) {
		List<String> userIdList = this.multiOrgUserAccountService.queryUserIdsLikeName(loginName); //.getUserByLoginNameIgnoreCase(loginName, PasswordAlgorithm.Plaintext.getValue());
		if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(userIdList)) {
			int size = userIdList.size() + 1;
			loginName += size;
			return getLoginName(loginName);
		} else {
			return loginName;
		}
	}

	@Override
	public MultiOrgDingUserInfo getByUserId(String userId) {
		Map<String, Object> params = Maps.newHashMap();
		params.put("userId", userId);
		List<MultiOrgDingUserInfo> lists = listByHQL("from MultiOrgDingUserInfo t where t.userId = :userId", params);
		if (lists != null && false == lists.isEmpty()) {
			return lists.get(0);
		}
		return null;
	}

	@Override
	public void updateUserFromDingtalkEventCallBack(JSONArray userIds) {
		for (int i = 0; i < userIds.size(); i++) {
			String userId = userIds.get(i).toString();
			String accessToken = DingtalkApiUtils.getAccessToken(); // 重新获取access_token
			JSONObject userobj = DingtalkApiUtils.getDingTalkUserInfo(userId, accessToken); // 调取钉钉接口获取用户详情
			if (userobj != null) {
				String unionid = userobj.getString("unionid");
				
				QueryItem item = this.getMultiOrgDingUserInfoByMap(unionid, userId);
				if(item != null) {
					
					String accountUuid = item.getString("accountuuid");
					String dingUserUuid = item.getString("dinguseruuid");
					String ptUserId = item.getString("id");
					
					String orderInDepts = userobj.get("orderInDepts") == null ? "" : userobj.getString("orderInDepts");
					String openId = userobj.get("openId") == null ? "" : userobj.getString("openId");
					String mobile = userobj.get("mobile") == null ? "" : userobj.getString("mobile");
					boolean active = userobj.get("active") == null ? false : userobj.getBoolean("active");
					String avatar = userobj.get("avatar") == null ? "" : userobj.getString("avatar");
					boolean isAdmin = userobj.get("isAdmin") == null ? false : userobj.getBoolean("isAdmin");
					String tags = userobj.get("tags") == null ? "" : userobj.getJSONObject("tags").toString();
					boolean isHide = userobj.get("isHide") == null ? false : userobj.getBoolean("isHide");
					String isLeaderInDepts = userobj.get("isLeaderInDepts") == null ? "" : userobj.getString("isLeaderInDepts");
					boolean isBoss = userobj.get("isBoss") == null ? false : userobj.getBoolean("isBoss");
					boolean isSenior = userobj.get("isSenior") == null ? false : userobj.getBoolean("isSenior");
					String name = userobj.get("name") == null ? "" : userobj.getString("name");
					String stateCode = userobj.get("stateCode") == null ? "" : userobj.getString("stateCode");
					String email = userobj.get("email") == null ? "" : userobj.getString("email");
					// 角色 
					JSONArray roles = userobj.get("roles") == null ? new JSONArray() : userobj.getJSONArray("roles");
					String roleUuids = addRolesFromDingtalk(roles);
					// 部门
					JSONArray departments = userobj.getJSONArray("department");
					// 职位  用户多部门的时候，同时在不同部门新增该职位。
					String position = userobj.getString("position");
					Map<String, Object> map = addJobFromDingtalkPosition(departments, position);

					// 登录名为拼音全拼  TODO 存在中文转拼音后，重名的问题，导致数据无法插入？
					// fixed 名称再加已存在的排序+1，例如已存在两个linyu，linyu2，则后续为拼音重复时，为linyu3
					String loginName = PinyinUtil.getPinYin(name);
					//loginName = getLoginName(loginName);
					
					OrgUserVo orgUserVo = new OrgUserVo();
					orgUserVo.setUuid(accountUuid);
					orgUserVo.setId(ptUserId);
					orgUserVo.setLoginName(loginName); // 平台登录名称使用手机号，保证唯一性
					orgUserVo.setCode(userId); // userid为钉钉返回的用户标识，这边作为code写入，后续平台可自行修改
					orgUserVo.setType(0);
					orgUserVo.setIsForbidden(0);
					orgUserVo.setSystemUnitId(system_unit_id);
					orgUserVo.setIsLocked(0);
					orgUserVo.setMobilePhone(mobile);
					orgUserVo.setMainEmail(email);
					orgUserVo.setUserName(name);
					orgUserVo.setRoleUuids(roleUuids);
					if (map != null) {
						orgUserVo.setMainJobId(map.get("mainJobId").toString());
						orgUserVo.setMainJobNamePath(map.get("mainJobNamePath").toString());
//						orgUserVo.setMainDepartmentIdPath(map.get("mainDepartmentIdPath").toString());
//						orgUserVo.setMainDepartmentNamePath(map.get("mainDepartmentNamePath").toString());
					}
					multiOrgService.modifyUser(orgUserVo);
					

					MultiOrgDingUserInfo userInfo = new MultiOrgDingUserInfo();
					userInfo.setUuid(dingUserUuid);
					userInfo.setName(name);
					userInfo.setUnionId(unionid);
					userInfo.setOrderInDepts(orderInDepts);
					userInfo.setOpenId(openId);
					userInfo.setRoles(roles.toString());
					userInfo.setMobile(mobile);
					userInfo.setActive(active ? 1 : 0);
					userInfo.setIsAdmin(isAdmin ? 1 : 0);
					userInfo.setIsHide(isHide ? 1 : 0);
					userInfo.setIsLeaderInDepts(isLeaderInDepts);
					userInfo.setIsBoss(isBoss ? 1 : 0);
					userInfo.setIsSenior(isSenior ? 1 : 0);
					userInfo.setStateCode(stateCode);
					userInfo.setDepartment(departments.toString());
					userInfo.setEmail(email);
					userInfo.setPosition(position);
					userInfo.setUserId(ptUserId);
					userInfo.setDing_userId(userId);
					userInfo.setAvatar(avatar);
					userInfo.setTags(tags);
					userInfo.setPtOriginPwd("0"); // 默认密码
					this.dao.update(userInfo);
				}
			}
		}
	}

	@Override
	public void deleteUserFromDingtalkEventCallBack(JSONArray userIds) {
		String auserIds = "";
		for (int i = 0; i < userIds.size(); i++) {
			String userId = userIds.get(i).toString();
			QueryItem item = this.getMultiOrgDingUserInfoByMap("", userId);
			if(item != null) {
				String accountUuid = item.getString("accountuuid");
				String dingUserUuid = item.getString("dinguseruuid");
				auserIds += accountUuid + ",";
				this.dao.delete(dingUserUuid);
			}
		}
		if(org.apache.commons.lang3.StringUtils.isNotBlank(auserIds))
			multiOrgService.deleteUsers(auserIds.split(","));
	}
}
